#include "StdAfx.h"
#include "XMLReader.h"



XMLReader::XMLReader(void)
{
	this->cola = new Cola();
	this->pila = new Pila();
	this->tagCount = 0;
}


XMLReader::~XMLReader(void)
{
}

void XMLReader::XMLFileReader(char* path)
{
	std::string STRING;
	std::ifstream myXML;
	myXML.open(path);
	while (!myXML.eof())
	{
		std::getline(myXML,	STRING);
		pila->push(STRING);//Empuja en la pila y la cola el documento linea por linea
		cola->encolar(STRING);//Luego el debuger extrae los tags que encuentra en cada linea y esto permite conocer exactamente donde estan los errores
	}
	myXML.close();
	//pila->invertirPila();//Ordenar la pila
	//cola->invertirCola();//Ordenar la cola
	printf("\n\nReading XML.........\n\n");
	DataWriterLog("\n\nReading XML.........\n\n");
	
	DebugStructure();//Debugger ON
	MuestraPila(pila);//DEBUG
	MuestraCola(cola);
	//MuestraCola(cola); DEBUG
	//Final de lectura
}

bool XMLReader::DebugStructure()
{
	Pila* pilaTags = new Pila();
	Cola* colaTags = new Cola();
	Pila* pilaAux = new Pila();//Pila auxiliares
	Cola* colaAux = new Cola();//Cola auxiliar
	//Debug de la pila
	printf("\n\nDebuger Output :\n\n");
	DataWriterLog("\n\nDebuger Output :\n\n");
	while(pila->top()!=NULL)
	{
		std::string str = pila->pop()->getDato().c_str();//Pop Data de la pila
		std::string tag;
		bool flag = false;// start copy flag
			for(int i=0; i<str.length();i++)
			{
				char dat = str.at(i); //DEBUG
				if(str.at(i) == '<')
				{
					flag = true;
				}

				if(flag == true)
				{
					tag += str.at(i);
				}

				if(str.at(i) == '>')
				{
					flag = false;
					pilaTags->push(tag);
					colaTags->encolar(tag);
					tagCount++;
					tag.clear();
				}
			}
		pilaAux->push(str);
	}
	pila = pilaAux;
	colaTags->invertirCola();
	pilaTags->invertirPila();
	//Show Results
	//Invertir Pila
	MuestraPila(pilaTags); //DEBUG
	MuestraCola(colaTags);	//DEBUG
	char colaA[100];
	printf("\n\nDEBUGGER MESSAGE :\n\n");
	strcpy(colaA,DetectXMLTagUnclosure(pilaTags));
	printf("%s",colaA);//AQUI GRANULAMOS LA PILA Y REVISAMOS CADA TAG DE CIERRE Y APERTURA
	printf("\n\n");
	printf("\nCantidad de XML Tags encontrados :\n");
	DataWriterLog("\nCantidad de XML Tags encontrados :\n");
	printf("%d",tagCount);
	char inttostr [10];
	itoa(tagCount,inttostr, 10);
	DataWriterLog(inttostr);
	printf("\n\n");
	return false;
}

void XMLReader::MuestraCola(Cola* cola)
{
	char colaA[1000];
	strcpy(colaA, cola->muestreCola());
	printf("%s",colaA);
	DataWriterLog(colaA);
}

void XMLReader::MuestraPila(Pila* pila)
{
	char pilaA[1000]; 
	strcpy(pilaA, pila->muestrePila());
	printf("%s",pilaA);
	DataWriterLog(pilaA);
}

void XMLReader::DataWriterLog(char* log)
{
	long size;
	try{
		std::ifstream istr("DebuggerLog.txt");
		if(istr)
		{
			size = istr.tellg();
			std::ofstream ostr;
			ostr.open("DebuggerLog.txt");
			ostr.write(log,size);
			ostr.flush();
			ostr.close();	
		}		
	}catch(char *ex)
	{
		printf("DebuggerLog.txt file is missing or corrupted");
	}
}

void XMLReader::DataWriterLog(std::string log)
{
	try{
		std::ofstream ostr;
		ostr.open("DebuggerLog.txt");
		ostr<<log;
		ostr.flush();
		ostr.close();
	}catch(char *ex)
	{
		printf("DebuggerLog.txt file is missing or corrupted");
	}
}

char* XMLReader::DetectXMLTagUnclosure(Pila* test)
{
	Pila* debug = new Pila();

	char error[100];
	std::string tag;
	size_t found;
	bool flag=false;//si se encuentra algun problema el flag indica la salida inmediata del ciclo
	while(!flag && test->top()!=NULL){
		//Para comparar se implementan dos metodos, 1 find y 2 substring.
		//1. Hay que determinar si el tag es de apertura o de clausura entonces decimos
		tag = test->pop()->getDato().c_str();
		found = tag.find("</");
		debug->push(tag);
		tag = test->pop()->getDato().c_str();
		strcpy(error,"MESSAGE: DEBUG SUCCESSFULL!");
		if(found!=std::string::npos)
		{
			//si es un tag de cierre la bandera se cambia a false y se hace un pop en la pila para saber si hay un match entre las etiquetas
			//se extrae la etiqueta para compararla con el tag
			std::string target = debug->pop()->getDato().c_str();
			std::string comp1 = tag.substr(found + 2);
			std::string comp2 = target.substr(found +2);
			if(comp1.compare(comp2) != 0){
			strcpy(error,"ERROR: TAG UNCLOSURE FOUND!");
			flag = true;		
			}
			debug->push(tag);//Este seria el tag que lanza el error
		}		
	}
	return error;
}
